﻿using LiveCharts;
using LiveCharts.Defaults;
using LiveCharts.Wpf;
using Modbus.Device;

using NewChillers.Helpers;
using NewChillers.Models;
using NewChillers.Models.Events;
using NewChillers.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using static NewChillers.ViewModels.ShellViewModel;

namespace NewChillers.ViewModels
{
    public class CommunicationViewModel : ObservableObject
    {
        private UserModel _currentUser;
        private readonly ShellViewModel _shellViewModel;
        //取消令牌
        private CancellationTokenSource _cancellationTokenSource;
        //串口
        private SerialPort serialPort;
        private bool _isCommConnected; // 通讯是否连接

        public CommunicationViewModel(UserModel userModel, ShellViewModel shellViewModel)
        {
            //ScanTest(); // 扫码枪模拟
            IsCommConnected = false;
            OpenBtnIsEnabled = true;
            LoadCollectContent();
            InitPortName();
            OpenSerialPortConnect();
            _currentUser = userModel;
            _shellViewModel = shellViewModel;

            // 初始化滚动趋势图(实时折线图)
            InitializeChart();
            //_ = StartChartUpdateAsync(); // 好像冗余了？

            // 订阅
            _shellViewModel.UserInfoUpdate += OnUserInfoUpdate;
        }

        #region 更新当前登录用户的信息 事件处理
        /// <summary>
        /// 接收到通知
        /// </summary>
        private void OnUserInfoUpdate(object sender, UserInfoUpdateEventArgs e)
        {
            // 空值检查，避免NullReferenceException
            if (e?.UpdatedUser != null)
            {
                _currentUser = e.UpdatedUser;
                Debug.WriteLine("Communication页面|用户信息已更新");
            }
            else
            {
                Debug.WriteLine("收到空的事件参数");
            }
        }

        /// <summary>
        /// 析构函数中的事件取消订阅
        /// </summary>
        ~CommunicationViewModel()
        {
            _shellViewModel.UserInfoUpdate -= OnUserInfoUpdate;
        }
        #endregion

        #region 属性
        public bool IsCommConnected
        {
            get => _isCommConnected;
            set
            {
                if (SetProperty(ref _isCommConnected, value))
                {
                    // 属性变化时自动触发事件
                    CommState state = value ? CommState.Connected : CommState.Disconnected;
                    AppEventCenter.RaiseCommStateChange(this, state);

                    // 启动折线图
                    // 通过方法控制图表
                    if (value)
                        StartChart();
                    else
                        StopChart();
                }
            }
        }

        //文本框
        private string _scanValue;
        private string _pressureValue;
        private string _pressureGasValue;
        private string _temperatureValue;

        //串口集合
        private ObservableCollection<string> _availablePortNames;
        private ObservableCollection<int> _selectBaudRates;
        private ObservableCollection<int> _selectStopBis;
        private ObservableCollection<string> _selectCheckDigBits;
        private ObservableCollection<int> _selectDataBits;

        //当前选中的串口号
        private string _portName;
        private int _baudRates;
        private int _stopBits;
        private string _checkDigBits;
        private int _dataBits;

        private bool _openBtnIsEnabled;


        public string ScanValue
        {
            get => _scanValue;
            set
            {
                _scanValue = value;
                RaisePropertyChanged();
            }
        }
        public ObservableCollection<string> AvailablePortNames
        {
            get => _availablePortNames;
            set
            {
                _availablePortNames = value;
                RaisePropertyChanged();
            }
        }
        public ObservableCollection<int> SelectBaudRates
        {
            get => _selectBaudRates;
            set
            {
                _selectBaudRates = value;
                RaisePropertyChanged();
            }
        }
        public ObservableCollection<int> SelectStopBis
        {
            get => _selectStopBis;
            set
            {
                _selectStopBis = value;
                RaisePropertyChanged();
            }
        }
        public ObservableCollection<string> SelectCheckDigBits
        {
            get => _selectCheckDigBits;
            set
            {
                _selectCheckDigBits = value;
                RaisePropertyChanged();
            }
        }
        public ObservableCollection<int> SelectDataBits
        {
            get => _selectDataBits;
            set
            {
                _selectDataBits = value;
                RaisePropertyChanged();
            }
        }

        //打开按钮
        public ICommand OpenConnectCommand
        {
            get
            {
                return new RelayCommand((arg) => OpenSerialPortConnect());
            }
        }

        //关闭按钮
        public ICommand CloseConnectCommand
        {
            get
            {
                return new RelayCommand((arg) => CloseSerialPortConnect());
            }
        }

        //串口号 变化
        public string PortName
        {
            get => _portName;
            set
            {
                _portName = value;
                RaisePropertyChanged();
                // 当串口号改变时，可进行一些相关操作，比如尝试重新连接等（这里可后续完善）
                //等待完善
            }
        }



        // 当前选中的波特率

        public int BaudRate
        {
            get => _baudRates;
            set
            {
                _baudRates = value;
                RaisePropertyChanged();
            }
        }

        public int StopBits
        {
            get => _stopBits;
            set
            {
                _stopBits = value;
                RaisePropertyChanged();
            }
        }
        public string CheckDigBits
        {
            get => _checkDigBits;
            set { _checkDigBits = value; RaisePropertyChanged(); }
        }
        public int DataBits
        {
            get => _dataBits;
            set { _dataBits = value; RaisePropertyChanged(); }
        }

        public bool OpenBtnIsEnabled
        {
            get => _openBtnIsEnabled;
            set
            {
                _openBtnIsEnabled = value;
                RaisePropertyChanged();
            }
        }

        public string PressureValue
        {
            get => _pressureValue;
            set
            {
                _pressureValue = value;
                RaisePropertyChanged();

                if (double.TryParse(value, out double currentPressure))
                {
                    _currentPressure = currentPressure;
                }
            }
        }
        public string PressureGasValue
        {
            get => _pressureGasValue;
            set
            {
                _pressureGasValue = value;
                RaisePropertyChanged();

                if (double.TryParse(value, out double currentPressureGas))
                {
                    _currentPressureGas = currentPressureGas;
                }
            }
        }
        public string TemperatureValue
        {
            get => _temperatureValue;
            set
            {
                _temperatureValue = value;
                RaisePropertyChanged();

                if (double.TryParse(value, out double currentTemperature))
                {
                    _currentTemperature = currentTemperature;
                }
            }
        }
        #endregion

        #region 串口相关

        /// <summary>
        /// 加载选项数据
        /// </summary>
        private void LoadCollectContent()
        {
            // 初始化波特率集合
            SelectBaudRates = new ObservableCollection<int> { 4800, 9600, 19200, 38400, 57600, 115200 };
            //默认9600
            BaudRate = 9600;

            // 初始化停止位集合
            SelectStopBis = new ObservableCollection<int> { 0, 1, 2, 3 };
            //默认1
            StopBits = 1;

            // 初始化校验位集合,
            SelectCheckDigBits = new ObservableCollection<string> { "None", "Even", "Odd", "Mark", "Space" };
            //默认 “none”
            CheckDigBits = "None";

            // 初始化数据位集合
            SelectDataBits = new ObservableCollection<int> { 5, 6, 7, 8 };
            //默认 8
            DataBits = 8;

        }
        /// <summary>
        /// 初始化串口名称
        /// </summary>
        private void InitPortName()
        {
            // 获取所有可用的串口名称
            var portNames = SerialPort.GetPortNames();
            if (portNames.Length > 0)
            {
                AvailablePortNames = new ObservableCollection<string>(portNames);
                // 设置默认选中第一个项
                PortName = AvailablePortNames.FirstOrDefault();
            }
            else
            {
                // 如果没有可用的串口，可以添加一个默认值或提示
                AvailablePortNames = new ObservableCollection<string> { "No ports available" };
                PortName = "No ports available";
            }
        }

        /// <summary>
        /// 打开串口连接
        /// </summary>
        private void OpenSerialPortConnect()
        {
            // 检查串口是否已经打开
            if (serialPort != null && serialPort.IsOpen)
            {
                MessageBox.Show("串口已打开");
                return;
            }

            try
            {
                // 将字符串转换为 Parity 枚举
                Parity parity;
                if (!Enum.TryParse(CheckDigBits, out parity))
                {
                    throw new ArgumentException("无效的校验位设置");
                }
                // 将 int 类型转换为 StopBits 枚举
                StopBits stopBits = ConvertToStopBits(StopBits);

                // 创建一个新的 SerialPort 实例
                serialPort = new SerialPort
                {
                    PortName = PortName,       // 串口号，例如 "COM1"
                    BaudRate = BaudRate,         // 波特率
                    Parity = parity,   // 校验位
                    DataBits = DataBits,            // 数据位
                    StopBits = stopBits, // 停止位
                    ReadTimeout = 500,       // 读取超时时间
                    WriteTimeout = 500       // 写入超时时间
                };

                // 打开串口
                if (!serialPort.IsOpen)
                {
                    serialPort.Open();
                    OpenBtnIsEnabled = false;
                }

                //Task.Run(() => MessageBox.Show("串口已成功打开"));
                if (serialPort.IsOpen)
                {
                    //// 进行实际的Modbus通讯测试（应用层面）尝试读取设备数据来验证真实连接
                    //IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
                    //ushort[] testData = master.ReadHoldingRegisters(1, 0, 1);

                    //if (testData != null && testData.Length > 0)
                    //{
                    //    IsCommConnected = true; // 连接成功
                    //    Debug.WriteLine("Modbus设备连接成功");
                    //}
                    //else
                    //{
                    //    IsCommConnected = false; // 硬件通但设备无响应
                    //    MessageBox.Show("串口已打开，但设备无响应");
                    //}

                    // 放在if外部 不管是否连接 串口都打开 读取任务都启动
                    // 启动读取数据的任务
                    _cancellationTokenSource = new CancellationTokenSource();
                    Task.Run(() => ReadDataAsync(_cancellationTokenSource.Token));
                    //_timer.Start();

                }
            }
            //catch (Exception ex) when (ex is TimeoutException)
            //{
            //    IsCommConnected = false; // 通讯超时 但可以算作打开了串口 等设备
            //    MessageBox.Show("设备响应超时，请检查连接");
            //}
            catch (Exception ex)
            {
                IsCommConnected = false; // 其他错误
                OpenBtnIsEnabled = true;
                MessageBox.Show($"打开串口时发生错误: {ex.Message}");
            }
        }

        //将 stopBits int 转换为 StopBits 枚举类型
        private StopBits ConvertToStopBits(int stopBits)
        {
            switch (stopBits)
            {
                case 0:
                    return System.IO.Ports.StopBits.None;
                case 1:
                    return System.IO.Ports.StopBits.One;
                case 2:
                    return System.IO.Ports.StopBits.Two;
                case 3:
                    return System.IO.Ports.StopBits.OnePointFive;
                default:
                    throw new ArgumentException("无效的停止位设置");
            }
        }

        ///<summary>
        /// 关闭串口连接
        /// </summary>
        private void CloseSerialPortConnect()
        {
            // 检查串口是否已经关闭
            if (serialPort == null || !serialPort.IsOpen)
            {
                OpenBtnIsEnabled = true;
                MessageBox.Show("串口未打开");
                return;
            }

            try
            {
                // 取消读取数据的任务
                _cancellationTokenSource?.Cancel();

                // 关闭串口
                serialPort.Close();
                IsCommConnected = false;
                OpenBtnIsEnabled = true;
                //_timer.Stop();
                MessageBox.Show("串口已成功关闭");
            }
            catch (Exception ex)
            {
                OpenBtnIsEnabled = false;
                MessageBox.Show($"关闭串口时发生错误: {ex.Message}");
            }
        }

        #endregion

        #region 数据读取逻辑
        private async Task ReadDataAsync(CancellationToken cancellationToken)
        {
            //modbus读取
            //创建MOdbusRtu通信协议实例
            IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    //读取压强值
                    ushort[] Pressure = await master.ReadHoldingRegistersAsync(1, 0, 1);
                    ushort[] PressureGas = await master.ReadHoldingRegistersAsync(1, 1, 1);
                    ushort[] Temperature = await master.ReadHoldingRegistersAsync(1, 2, 1);

                    if (Pressure != null && PressureGas != null && Temperature != null)
                    {
                        IsCommConnected = true;

                        PressureValue = Pressure.Length > 0 ? Pressure[0].ToString() : "0";
                        PressureGasValue = PressureGas.Length > 0 ? PressureGas[0].ToString() : "0";
                        TemperatureValue = Temperature.Length > 0 ? Temperature[0].ToString() : "0";

                        Console.WriteLine($"Pressure: {PressureValue}");
                        Console.WriteLine($"PressureGas: {PressureGasValue}");
                        Console.WriteLine($"Temperature: {TemperatureValue}");

                        //await Task.Delay(100, cancellationToken);

                        //ConvertDataToStatic();
                        await ConvertDataToStatic();
                    }
                    else
                    {
                        IsCommConnected = false;
                    }

                    await Task.Delay(100, cancellationToken);  // 移到循环末尾

                    //PressureValue = Pressure.Length > 0 ? Pressure[0].ToString() : "0";
                    //PressureGasValue = PressureGas.Length > 0 ? PressureGas[0].ToString() : "0";
                    //TemperatureValue = Temperature.Length > 0 ? Temperature[0].ToString() : "0";

                    //Console.WriteLine($"Pressure: {PressureValue}");
                    //Console.WriteLine($"PressureGas: {PressureGasValue}");
                    //Console.WriteLine($"Temperature: {TemperatureValue}");
                    //await Task.Delay(100, cancellationToken);

                    //ConvertDataToStatic();
                }
                catch (OperationCanceledException)
                {
                    // 操作被取消，正常退出
                    IsCommConnected = false;
                    break;
                }
                catch (Exception ex)
                {
                    // 处理异常
                    IsCommConnected = false;
                    Console.WriteLine($"Error reading Modbus data: {ex.Message}");
                }
            }


        }

        ///数据转化为静态变量
        private async Task ConvertDataToStatic()
        {

            try
            {
                // 将当前读取的数据保存为静态变量，供其他ViewModel访问
                if (!string.IsNullOrEmpty(PressureValue))
                {
                    DeviceDataStore.VacuumValue_real = Convert.ToDouble(PressureValue);
                }

                if (!string.IsNullOrEmpty(PressureGasValue))
                {
                    DeviceDataStore.HeliumValue_real = Convert.ToDouble(PressureGasValue);
                }

                if (!string.IsNullOrEmpty(TemperatureValue))
                {
                    DeviceDataStore.TemperatureValue_real = Convert.ToDouble(TemperatureValue);
                }
            }
            catch (Exception ex)
            {

            }

        }

        #endregion

        #region 扫码枪相关
        //测试    随机生成一个字符串    类似 P10001
        private string GenerateRandomString()
        {
            string characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            int length = 8;
            StringBuilder sb = new StringBuilder();
            Random random = new Random();

            for (int i = 0; i < length; i++)
            {
                int index = random.Next(characters.Length);
                char randomChar = characters[index];
                sb.Append(randomChar);
            }

            return sb.ToString();
        }
        private async void ScanTest()
        {
            //每10秒生成一个随机字符串
            // 持续每10秒生成一个随机字符串
            while (true)
            {
                try
                {
                    await Task.Delay(30000); // 每10秒生成一次
                    DeviceDataStore.ScanValue_real = GenerateRandomString();
                    ScanValue = DeviceDataStore.ScanValue_real;

                }
                catch (Exception ex)
                {
                    // 处理异常，避免任务崩溃
                    Console.WriteLine($"ScanTest error: {ex.Message}");
                }
            }
        }

        #endregion

        #region 实时图
        private double _currentPressure;
        private double _currentPressureGas;
        private double _currentTemperature;

        private static DateTime _axisStartTime;

        private bool _isReadingChart = false;
        public bool IsReadingChart
        {
            get => _isReadingChart;
            set => SetProperty(ref _isReadingChart, value);
        }

        private SeriesCollection _seriesCollectionChart1;
        public SeriesCollection SeriesCollectionChart1
        {
            get => _seriesCollectionChart1;
            set => SetProperty(ref _seriesCollectionChart1, value);
        }

        private SeriesCollection _seriesCollectionChart2;
        public SeriesCollection SeriesCollectionChart2
        {
            get => _seriesCollectionChart2;
            set => SetProperty(ref _seriesCollectionChart2, value);
        }

        private SeriesCollection _seriesCollectionChart3;
        public SeriesCollection SeriesCollectionChart3
        {
            get => _seriesCollectionChart3;
            set => SetProperty(ref _seriesCollectionChart3, value);
        }

        /// <summary>
        /// X轴时间标签格式化器
        /// </summary>
        public Func<double, string> LabelsFormatter { get; } = value =>
        {
            var secondsFromStart = (int)value;
            var displayTime = _axisStartTime.AddSeconds(secondsFromStart);
            var secondsAgo = (int)(DateTime.Now - displayTime).TotalSeconds;

            // 向下取整
            //return secondsAgo == 0 ? "现在" : $"{secondsAgo}秒前";
            // 四舍五入
            //var roundedSecondsAgo = (int)Math.Round(secondsAgo);
            //return roundedSecondsAgo == 0 ? "现在" : $"{roundedSecondsAgo}秒前";
            // 强制对齐到5秒倍数
            var alignedSeconds = ((secondsAgo + 2) / 5) * 5; // +2是为了更好的四舍五入
            return alignedSeconds == 0 ? "现在" : $"{alignedSeconds}秒前";
        };

        /// <summary>
        /// Y轴 浮点数精度
        /// </summary>
        //// 压强数据（1位小数）
        //public Func<double, string> PressureYFormatter { get; } = value =>
        //{
        //    if (Math.Abs(value) < 0.1)
        //        return "0";
        //    return $"{value:F1}";
        //};
        //// 精密压力数据（3位小数）
        //public Func<double, string> GasPressureYFormatter { get; } = value =>
        //{
        //    if (Math.Abs(value) < 0.001)
        //        return "0";
        //    return $"{value:F3}";  // 固定显示3位小数
        //};
        //// 温度数据（1位小数）
        //public Func<double, string> TemperatureYFormatter { get; } = value =>
        //{
        //    if (Math.Abs(value) < 0.1)
        //        return "0";
        //    return $"{value:F1}";  // 显示1位小数
        //};
        // 还是返回整数吧(四舍五入版本 而非向下取整 向下取整会导致 6.9999999999 -> 6 而不是7)
        public Func<double, string> IntYFormatter { get; } = value =>
        {
            return $"{value:F0}";
        };

        /// <summary>
        /// 初始化图表
        /// </summary>
        private void InitializeChart()
        {
            _axisStartTime = DateTime.Now;

            // 初始化 Y 轴（你的原有代码）
            //PressureYAxis = CreateCustomYAxis("压强/Pa", 14, Brushes.DodgerBlue);
            //GasPressureYAxis = CreateCustomYAxis("燃气压力/Pa", 14, Brushes.Green);
            //TemperatureYAxis = CreateCustomYAxis("温度/℃", 14, Brushes.Red);

            // 压强值图表
            SeriesCollectionChart1 = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "压力值",
                    Values = new ChartValues<ObservablePoint>(),
                    PointGeometry = null,
                    //PointGeometry = DefaultGeometries.Circle, // 改为这个显示点
                    //PointGeometrySize = 6, // 设置点的大小
                    LineSmoothness = 0,
                    StrokeThickness = 2
                }
            };

            // 精密压力图表（复用LineSeries初始化逻辑）
            SeriesCollectionChart2 = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "燃气压力值",
                    Values = new ChartValues<ObservablePoint>(),
                    PointGeometry = null,
                    LineSmoothness = 0,
                    StrokeThickness = 2
                }
            };

            // 温度图表（复用LineSeries初始化逻辑）
            SeriesCollectionChart3 = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "温度值",
                    Values = new ChartValues<ObservablePoint>(),
                    PointGeometry = null,
                    LineSmoothness = 0,
                    StrokeThickness = 2
                }
            };
        }

        /// <summary>
        /// 启动数据维护任务
        /// </summary>
        private async Task StartChartUpdateAsync()
        {
            while (IsReadingChart)
            {
                await Task.Delay(1000);
                AddChartData();
                //CheckDataCount();
            }
        }

        /// <summary>
        /// 添加数据点
        /// </summary>
        private void AddChartData()
        {
            //var lineSeries = SeriesCollectionChart1[0] as LineSeries;
            var pressureSeries = SeriesCollectionChart1[0] as LineSeries;
            var gasPressureSeries = SeriesCollectionChart2[0] as LineSeries;
            var temperatureSeries = SeriesCollectionChart3[0] as LineSeries;

            //if (lineSeries?.Values == null) return;
            if (pressureSeries?.Values == null || gasPressureSeries?.Values == null || temperatureSeries?.Values == null)
                return;

            Application.Current?.Dispatcher?.Invoke(() =>
            {
                var now = DateTime.Now;
                var timeOffset = (now - _axisStartTime).TotalSeconds;

                // 添加数据点+长度控制逻辑
                // 压强值
                pressureSeries.Values.Add(new ObservablePoint(timeOffset, _currentPressure));
                if (pressureSeries.Values.Count > 20)
                    pressureSeries.Values.RemoveAt(0);

                // 精密压力值（复用相同逻辑，仅修改数据来源）
                gasPressureSeries.Values.Add(new ObservablePoint(timeOffset, _currentPressureGas));
                if (gasPressureSeries.Values.Count > 20)
                    gasPressureSeries.Values.RemoveAt(0);

                // 温度值（复用相同逻辑，仅修改数据来源）
                temperatureSeries.Values.Add(new ObservablePoint(timeOffset, _currentTemperature));
                if (temperatureSeries.Values.Count > 20)
                    temperatureSeries.Values.RemoveAt(0);
            });
        }

        private async void StartChart()
        {
            try
            {
                IsReadingChart = true;
                await StartChartUpdateAsync();
            }
            catch (Exception ex)
            {
                // 处理启动异常
                Debug.WriteLine($"图表启动失败: {ex.Message}");
                IsReadingChart = false;
            }
        }

        private void StopChart()
        {
            IsReadingChart = false;
            // 可选：清空图表数据
            ClearChartData();
        }

        private void ClearChartData()
        {
            var pressureSeries = SeriesCollectionChart1[0] as LineSeries;
            var gasPressureSeries = SeriesCollectionChart2[0] as LineSeries;
            var temperatureSeries = SeriesCollectionChart3[0] as LineSeries;

            Application.Current?.Dispatcher?.Invoke(() =>
            {
                pressureSeries?.Values?.Clear();
                gasPressureSeries?.Values?.Clear();
                temperatureSeries?.Values?.Clear();
            });
        }

        #endregion
    }
}
